#pragma execution_charactor_set("utf-8")
#include <QtCore/QCoreApplication>
#include <QFile>
#include <QDataStream>
#include <QDebug>

#pragma pack(push)
#pragma pack(1)

struct Fat12Header
{
    char BS_OEMName[8];
    ushort BPB_BytsPerSec;
    uchar BPB_SecPerClus;
    ushort BPB_RsvdSecCnt;
    uchar BPB_NumFATs;
    ushort BPB_RootEntCnt;
    ushort BPB_TotSec16;
    uchar BPB_Media;
    ushort BPB_FATSz16;
    ushort BPB_SecPerTrk;
    ushort BPB_NumHeads;
    uint BPB_HiddSec;
    uint BPB_TotSec32;
    uchar BS_DrvNum;
    uchar BS_Reserved1;
    uchar BS_BootSig;
    uint BS_VolID;
    char BS_VolLab[11];
    char BS_FileSysType[8];
};

struct RootEntry{
    char DIR_Name[11];
    uchar DIR_Attr;
    uchar reserve[10];
    ushort DIR_WrtTime;
    ushort DIR_WrtDate;
    ushort DIR_FstClus;
    uint DIR_FileSize;
};

#pragma pack(pop)

void PrintHeader(Fat12Header& rf, QString p)
{
    QFile file(p);

    if( file.open(QIODevice::ReadOnly) )
    {
        QDataStream in(&file);

        file.seek(3);

        in.readRawData(reinterpret_cast<char*>(&rf), sizeof(rf));

        rf.BS_OEMName[7] = 0;
        rf.BS_VolLab[10] = 0;
        rf.BS_FileSysType[7] = 0;

        qDebug() << "BS_OEMName: " << rf.BS_OEMName;
        qDebug() << "BPB_BytsPerSec: " << hex << rf.BPB_BytsPerSec;
        qDebug() << "BPB_SecPerClus: " << hex << rf.BPB_SecPerClus;
        qDebug() << "BPB_RsvdSecCnt: " << hex << rf.BPB_RsvdSecCnt;
        qDebug() << "BPB_NumFATs: " << hex << rf.BPB_NumFATs;
        qDebug() << "BPB_RootEntCnt: " << hex << rf.BPB_RootEntCnt;
        qDebug() << "BPB_TotSec16: " << hex << rf.BPB_TotSec16;
        qDebug() << "BPB_Media: " << hex << rf.BPB_Media;
        qDebug() << "BPB_FATSz16: " << hex << rf.BPB_FATSz16;
        qDebug() << "BPB_SecPerTrk: " << hex << rf.BPB_SecPerTrk;
        qDebug() << "BPB_NumHeads: " << hex << rf.BPB_NumHeads;
        qDebug() << "BPB_HiddSec: " << hex << rf.BPB_HiddSec;
        qDebug() << "BPB_TotSec32: " << hex << rf.BPB_TotSec32;
        qDebug() << "BS_DrvNum: " << hex << rf.BS_DrvNum;
        qDebug() << "BS_Reserved1: " << hex << rf.BS_Reserved1;
        qDebug() << "BS_BootSig: " << hex << rf.BS_BootSig;
        qDebug() << "BS_VolID: " << hex << rf.BS_VolID;
        qDebug() << "BS_VolLab: " << rf.BS_VolLab;
        qDebug() << "BS_FileSysType: " << rf.BS_FileSysType;

        file.seek(510);

        uchar b510 = 0;
        uchar b511 = 0;

        in.readRawData(reinterpret_cast<char*>(&b510), sizeof(b510));
        in.readRawData(reinterpret_cast<char*>(&b511), sizeof(b511));

        qDebug() << "Byte 510: " << hex << b510;
        qDebug() << "Byte 511: " << hex << b511;
    }

    file.close();
}
///查找根目录区中的目录文件项
/// 每个目录项代表根目录中的一个文件索引
RootEntry FindRootEntry(Fat12Header& rf,QString p ,int i)
{
    RootEntry ret = {{0}};

    QFile file(p);

    if(file.open(QIODevice::ReadOnly) && (0 <= i) && ( i < rf.BPB_RootEntCnt))
    {
        QDataStream in(&file);
        ///计算偏移  从偏移地址开始读
        file.seek(19 * rf.BPB_BytsPerSec + i * sizeof(RootEntry));
        in.readRawData(reinterpret_cast<char*>(&ret),sizeof(ret));
    }

    file.close();

    return ret;
}

RootEntry FindRootEntry(Fat12Header &rf, QString p, QString fn)
{
    RootEntry ret = {{0}};

    for(int i = 0;i<rf.BPB_RootEntCnt;i++)
    {
        RootEntry re = FindRootEntry(rf,p,i);
        if(re.DIR_Name[0] != '\0')
        {
            int d = fn.lastIndexOf(".");
            QString name = QString(re.DIR_Name).trimmed();
            if(d >= 0)
            {
                ///获取.的前半部分he后半部分
                QString n = fn.mid(0,d);
                QString p = fn.mid(d+1);
                ///是否以文件名开头he后缀名结尾
                if(name.startsWith(n) && name.endsWith(p))
                {
                    ret = re;
                    break;
                }
            }
            else
            {
                if(fn == name)
                {
                    ret = re;
                    break;
                }
            }
        }
    }

    return ret;
}

void PrintRootEntry(Fat12Header& rf,QString p)
{
    for(int i = 0;i<rf.BPB_RootEntCnt;i++)
    {
        RootEntry re = FindRootEntry(rf,p,i);
        ///判断文件名是否为空
        if(re.DIR_Name[0] != '\0')
        {
            qDebug()<<i<<":";
            ///打印目录的名字
            qDebug()<<"DIR_Name"<<hex<<re.DIR_Name;
            ///打印属性
            qDebug()<<"DIR_Attr:"<<hex<<re.DIR_Attr;
            ////打印最后一次写入的时间日期
            qDebug()<<"DIR_WrtData:"<<hex<<re.DIR_WrtDate;
            qDebug()<<"DIR_WrtTime:"<<hex<<re.DIR_WrtTime;
            ///打印起始位置he长度
            qDebug()<<"DIR_FstClus:"<<hex<<re.DIR_FstClus;
            qDebug()<<"DIR_FileSize:"<<hex<<re.DIR_FileSize;
        }
    }
}

QVector<ushort> ReadFat(Fat12Header& rf,QString p)
{
    QFile file(p);

    int size = rf.BPB_BytsPerSec*9;
    uchar* fat = new uchar[];
    QVector<ushort>ret(size *2 / 3,0xFFFF);

    if(file.open(QIODevice::ReadOnly))
    {
        QDataStream in(&file);

        file.seek(rf.BPB_BytsPerSec * 1);
        in.readRawData(reinterpret_cast<char*>(fat),size);


    }

}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QString img = "/home/ubuntu/OS_learn/chapter_4/data.img";
    Fat12Header f12;
    qDebug()<<"Read Header";
    PrintHeader(f12, img);

    qDebug()<<endl;

    qDebug()<<"Print Root Entry";

    ///PrintRootEntry(f12,img);

    RootEntry re = FindRootEntry(f12,img,"TEST.TXT");

    ///打印目录的名字
    qDebug()<<"DIR_Name"<<hex<<re.DIR_Name;
    ///打印属性
    qDebug()<<"DIR_Attr:"<<hex<<re.DIR_Attr;
    ////打印最后一次写入的时间日期
    qDebug()<<"DIR_WrtData:"<<hex<<re.DIR_WrtDate;
    qDebug()<<"DIR_WrtTime:"<<hex<<re.DIR_WrtTime;
    ///打印起始位置he长度
    qDebug()<<"DIR_FstClus:"<<hex<<re.DIR_FstClus;
    qDebug()<<"DIR_FileSize:"<<hex<<re.DIR_FileSize;
    
    return a.exec();
}
